package com.hyt.it.ogt.ykcj.service.grade.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.hyt.it.ogt.ykcj.common.annotation.ChangedExam;
import com.hyt.it.ogt.ykcj.common.constant.Constants;
import com.hyt.it.ogt.ykcj.common.constant.ImportFieldConstants;
import com.hyt.it.ogt.ykcj.common.core.domain.AjaxResult;
import com.hyt.it.ogt.ykcj.common.core.domain.entity.SysUser;
import com.hyt.it.ogt.ykcj.common.enums.BizErrorCode;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.DateUtils;
import com.hyt.it.ogt.ykcj.common.utils.IdUtils;
import com.hyt.it.ogt.ykcj.common.utils.SecurityUtils;
import com.hyt.it.ogt.ykcj.common.utils.StringUtils;
import com.hyt.it.ogt.ykcj.common.utils.spring.SpringUtils;
import com.hyt.it.ogt.ykcj.domain.exam.ExamNameConfig;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectNameConfig;
import com.hyt.it.ogt.ykcj.domain.grade.ExamineeGradeInfo;
import com.hyt.it.ogt.ykcj.domain.grade.ExamineeSubjectGradeInfo;
import com.hyt.it.ogt.ykcj.domain.vo.*;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ExamineeGradeInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ExamineeSubjectGradeInfoMapper;
import com.hyt.it.ogt.ykcj.service.exam.IChangedExamInfoService;
import com.hyt.it.ogt.ykcj.service.grade.ExportUtils;
import com.hyt.it.ogt.ykcj.service.grade.IExamineeGradeInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IExamineeSubjectGradeInfoService;
import com.hyt.it.ogt.ykcj.service.grade.ImportAbstractService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 考生成绩信息Service业务层处理
 * 
 * @author admin
 * @date 2021-06-16
 */
@Service
public class ExamineeGradeInfoServiceImpl implements IExamineeGradeInfoService
{
    private static final Logger log = LoggerFactory.getLogger(ExamineeGradeInfoServiceImpl.class);

    @Autowired
    private ExamineeGradeInfoMapper examineeGradeInfoMapper;

    @Autowired
    private ExamineeSubjectGradeInfoMapper subjectGradeInfoMapper;

    @Autowired
    private ExamSubjectInfoMapper subjectInfoMapper;


    @Autowired
    private IExamineeSubjectGradeInfoService subjectGradeInfoService;

    @Autowired
    private ExamNameConfigMapper nameConfigMapper;

    @Autowired
    private ExamSubjectNameConfigMapper subjectNameConfigMapper;

    @Autowired
    IChangedExamInfoService changedExamInfoService;

    @Resource(name = "threadPoolTaskExecutor")
    ThreadPoolTaskExecutor threadPoolTaskExecutor ;

    /**
     * 查询考生成绩信息
     * 
     * @param gradeId 考生成绩信息ID
     * @return 考生成绩信息
     */
    @Override
    public ExamineeGradeInfo selectExamineeGradeInfoById(String gradeId)
    {
        return examineeGradeInfoMapper.selectExamineeGradeInfoById(gradeId);
    }

    /**
     * 查询考生成绩信息列表
     * 
     * @param examineeGradeInfo 考生成绩信息
     * @return 考生成绩信息
     */
    @Override
    public List<ExamineeGradeInfo> selectExamineeGradeInfoList(ExamineeGradeInfo examineeGradeInfo)
    {
        return examineeGradeInfoMapper.selectExamineeGradeInfoList(examineeGradeInfo);
    }

    /**
     * 新增考生成绩信息
     * 
     * @param examineeGradeInfoVo 考生成绩信息vo
     * @return 结果
     */
    @Override
    @ChangedExam
    @Transactional(rollbackFor = Exception.class)
    public boolean insertExamineeGradeInfo(AddExamineeGradeInfoVo examineeGradeInfoVo, SysUser user)
    {
        boolean result = true;
        // 插入考试信息
        ExamineeGradeInfo examineeGradeInfo = new ExamineeGradeInfo();
        examineeGradeInfo.setExamId(examineeGradeInfoVo.getExamId());
        examineeGradeInfo.setExamineeIdCode(examineeGradeInfoVo.getExamineeIdCode());
        // 查询考生是否存在
        List<ExamineeGradeInfo> existInfoList = examineeGradeInfoMapper.findExistGradeInfo(examineeGradeInfo);
        if (CollectionUtils.isNotEmpty(existInfoList)){
            throw new CustomException(BizErrorCode.GRADE_E0008);
        }

        // 组装考生成绩信息
        BeanUtils.copyProperties(examineeGradeInfoVo,examineeGradeInfo);
        // 插入考试科目成绩信息
        examineeGradeInfo.setCreateTime(DateUtils.getNowDate());
        String gradeId = IdUtils.generateId();
        examineeGradeInfo.setGradeId(gradeId);
        examineeGradeInfo.setCreateBy(user.getUserName());
        // 初始化科目成绩信息
        if (!CollectionUtils.isEmpty(examineeGradeInfoVo.getSubjectGradeInfoList())){
            List<ExamSubjectInfo> examSubjectInfoList = subjectInfoMapper.selectExamSubjectInfoListById(examineeGradeInfo.getExamId());
            Map<String,ExamSubjectInfo> subjectInfoMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(examSubjectInfoList)){
                subjectInfoMap = examSubjectInfoList.stream().collect(Collectors.toMap(ExamSubjectInfo::getId,subjectInfo->subjectInfo));
            }
            for (ExamineeSubjectGradeInfo examineeSubjectGradeInfo:examineeGradeInfoVo.getSubjectGradeInfoList()) {
                examineeSubjectGradeInfo.setExamId(examineeGradeInfoVo.getExamId());
                subjectGradeInfoService.initSubjectGradeInfo(examineeSubjectGradeInfo,subjectInfoMap,gradeId,user);
            }
        }
        // 默认成绩合格，只要有一门学科不合格则总成绩不合格
        String passFlag = Constants.PASS_FLAT_Y;
        // 查询考试对应的科目数
        List<ExamSubjectVo> subjectVoList = subjectInfoMapper.selectExamSubjectInfoByExamId(examineeGradeInfoVo.getExamId());
        // 如果当前考试的科目数跟考试的科目数不一致，需要查询当前考试没有的科目之前成绩是否合格
        if (subjectVoList.size() != examineeGradeInfoVo.getSubjectGradeInfoList().size()){
            passFlag = Constants.PASS_FLAT_N;
        }else {
            for (ExamineeSubjectGradeInfo subjectGradeInfo:examineeGradeInfoVo.getSubjectGradeInfoList()) {
                if (Constants.PASS_FLAT_N.equals(subjectGradeInfo.getPassFlag())){
                    passFlag = Constants.PASS_FLAT_N;
                    break;
                }
            }
        }

        examineeGradeInfo.setPassFlag(passFlag);
        examineeGradeInfo.setPassDate(Constants.PASS_FLAT_Y.equals(passFlag) ? DateUtils.getDate():null);

        // 插入考生信息
        examineeGradeInfoMapper.insertExamineeGradeInfo(examineeGradeInfo);
        if (CollectionUtils.isNotEmpty(examineeGradeInfoVo.getSubjectGradeInfoList())){
            // 插入考生科目成绩信息
            subjectGradeInfoMapper.batchInsertSubjectGradeInfo(examineeGradeInfoVo.getSubjectGradeInfoList());
        }

        // 插入需要变更的考试信息
        Constants.changedExamId.set(examineeGradeInfoVo.getExamId());
        return result;
    }

    /**
     * 修改考生成绩信息
     * 
     * @param examineeGradeInfo 考生成绩信息
     * @return 结果
     */
    @Override
    @ChangedExam
    public void updateExamineeGradeInfo(EditExamineeGradeInfoVo examineeGradeInfo)
    {
        ExamineeGradeInfo oldInfo = examineeGradeInfoMapper.selectExamineeGradeInfoById(examineeGradeInfo.getGradeId());
        if (null == oldInfo){
            throw new CustomException(BizErrorCode.GRADE_E0001);
        }
        // 成绩导入页面允许改身份证,成绩归档页面不允许
        if (Constants.EDIT_TYPE_0.equals(examineeGradeInfo.getEditType())){
            // 如果修改了身份证，需要判断是否已经存在改身份证
            if (!oldInfo.getExamineeIdCode().equals(examineeGradeInfo.getExamineeIdCode())){
                log.info("考生修改了证件号,修改前为{},修改后为{}",oldInfo.getExamineeIdCode(),examineeGradeInfo.getExamineeIdCode());
                List<ExamineeGradeInfo> list = examineeGradeInfoMapper.findExistGradeInfo(examineeGradeInfo);
                if (list.size() > 0){
                    throw new CustomException(BizErrorCode.GRADE_E0008);
                }
            }
        }

        examineeGradeInfo.setUpdateBy(SecurityUtils.getUsername());
        examineeGradeInfo.setUpdateTime(DateUtils.getNowDate());
        // 修改考生信息
        examineeGradeInfoMapper.updateExamineeGradeInfo(examineeGradeInfo);
        // 如果修改了考生的档案编号，需要改考生的所有历史档案编号
        if (!oldInfo.getArchivesNo().equals(examineeGradeInfo.getArchivesNo())){
            log.info("考生修改了档案号,修改前为{},修改后为{}",oldInfo.getArchivesNo(),examineeGradeInfo.getArchivesNo());
            examineeGradeInfoMapper.updateExamineeArchiveNo(examineeGradeInfo.getArchivesNo(),examineeGradeInfo.getExamineeIdCode());
        }
        // 插入需要变更的考试信息
        Constants.changedExamId.set(oldInfo.getExamId());
    }

    /**
     * 批量删除考生成绩信息
     * 
     * @param gradeIds 需要删除的考生成绩信息ID
     * @return 结果
     */
    @Override
    public int deleteExamineeGradeInfoByIds(String[] gradeIds)
    {
        return examineeGradeInfoMapper.deleteExamineeGradeInfoByIds(gradeIds);
    }

    /**
     * 删除考生成绩信息信息
     * 
     * @param gradeId 考生成绩信息ID
     * @return 结果
     */
    @Override
    @ChangedExam
    public void deleteExamineeGradeInfoById(String gradeId)
    {

        // 先删除考生成绩信息，再删除考生科目成绩信息
        ExamineeGradeInfo examineeGradeInfo = examineeGradeInfoMapper.selectExamineeGradeInfoById(gradeId);
        if (null == examineeGradeInfo){
            throw new CustomException(BizErrorCode.GRADE_E0001);
        }

        // 删除考生成绩信息
        examineeGradeInfoMapper.deleteExamineeGradeInfoById(gradeId);

        // 删除考生科目成绩信息
        subjectGradeInfoMapper.deleteSubjectGradeByGradeId(gradeId);

        // 插入需要更新的考试信息
        Constants.changedExamId.set(examineeGradeInfo.getExamId());
    }

    @Override
    @Transactional
    public void archiveGradeInfo(String type, String id, SysUser sysUser) {
        log.info("成绩归档begin...,归档类型为{},用户为{}",id,sysUser.getUserName());

        Date curDate = DateUtils.getNowDate();
        // 成绩信息归档
        if (Constants.ARCHIVE_TYPE_0.equals(type)){
            log.info("考生成绩信息归档");
            ExamineeGradeInfo gradeInfo = examineeGradeInfoMapper.selectExamineeGradeInfoById(id);
            if (null == gradeInfo){
                throw new CustomException(BizErrorCode.GRADE_E0001);
            }
            // 更新成绩信息归档
            updateGradeInfoArchivedStatus(gradeInfo,sysUser,Constants.ARCHIVED_STATUS_Y);
            List<ExamineeSubjectGradeInfo> examineeSubjectGradeInfoList = subjectGradeInfoMapper.selectSubjectGradeInfoListByGradeId(id);
            if (CollectionUtils.isNotEmpty(examineeSubjectGradeInfoList)){
                // 设置成绩有效期
                setValidGradeDate(examineeSubjectGradeInfoList,gradeInfo.getExamId(),curDate,sysUser.getUserName());
                //  更新所有科目成绩为归档
                subjectGradeInfoMapper.batchUpdateSbujectGradeInfo(examineeSubjectGradeInfoList);

            }

        }else {
            log.info("考生科目成绩信息归档");
            ExamineeSubjectGradeInfo subjectGradeInfo = subjectGradeInfoMapper.selectExamineeSubjectGradeInfoById(id);
            if (null == subjectGradeInfo){
                throw new CustomException(BizErrorCode.GRADE_E0003);
            }

            ExamSubjectInfo examSubjectInfo = subjectGradeInfoMapper.querySubjectEffectiveDateBySubjectGradeId(id);
            if (StringUtils.isNotEmpty(examSubjectInfo.getEffectiveDate())){
                String endData = getValidPeriodEndDate(examSubjectInfo.getEffectiveDate());
                subjectGradeInfo.setValidPeriodEndDate(endData);
                subjectGradeInfo.setInvalidDate(endData);

            }
            subjectGradeInfo.setValidPeriodStartDate(DateUtils.getDate());
            subjectGradeInfo.setArchivedStatus(Constants.ARCHIVED_STATUS_Y);
            subjectGradeInfo.setArchivedDate(curDate);
            subjectGradeInfo.setUpdateBy(sysUser.getUserName());
            subjectGradeInfo.setUpdateTime(DateUtils.getNowDate());
            subjectGradeInfoMapper.updateExamineeSubjectGradeInfo(subjectGradeInfo);
            ExamineeGradeInfo gradeInfo = examineeGradeInfoMapper.selectExamineeGradeInfoById(subjectGradeInfo.getGradeId());
            if (null == gradeInfo){
                throw new CustomException(BizErrorCode.GRADE_E0001);
            }
            // 判断所有科目成绩是否都已经归档，都归档了则更新总成绩归档
            String archivedStatus = checkGradeInfoArchivedStatus(subjectGradeInfo.getGradeId());
            if (!archivedStatus.equals(gradeInfo.getArchivedStatus())){
                updateGradeInfoArchivedStatus(gradeInfo,sysUser,archivedStatus);
            }

        }

        log.info("成绩归档结束");
    }

    /**
     * 获取成绩有效期截止日期
     * @param effectiveDate
     * @return
     */
    private String getValidPeriodEndDate(String effectiveDate){
        SimpleDateFormat formats = new SimpleDateFormat(DateUtils.YYYY_MM_DD);
        Calendar c = Calendar.getInstance();
        c.add(Calendar.YEAR,+Integer.parseInt(effectiveDate));
        Date tmp =  c.getTime();
        return formats.format(tmp);
    }

    /**
     * 更新归档状态
     * @param gradeInfo
     * @param sysUser
     * @param archivedStatus
     */
    private void updateGradeInfoArchivedStatus(ExamineeGradeInfo gradeInfo,SysUser sysUser,String archivedStatus){
        gradeInfo.setArchivedStatus(archivedStatus);
        gradeInfo.setUpdateBy(sysUser.getUserName());
        gradeInfo.setUpdateTime(DateUtils.getNowDate());
        examineeGradeInfoMapper.updateExamineeGradeInfo(gradeInfo);
    }

    /**
     * 校验所有科目是否已归档
     */
    public String checkGradeInfoArchivedStatus(String gradeId){
        String passFlag = Constants.ARCHIVED_STATUS_Y;
        // 查询考生科目成绩列表
        List<ExamineeSubjectGradeInfo> subjectGradeInfoList = subjectGradeInfoMapper.selectSubjectGradeInfoListByGradeId(gradeId);
        if (!CollectionUtils.isEmpty(subjectGradeInfoList)){
            // 判断每科成绩的通过状态来决定总成绩是否通过
            for (ExamineeSubjectGradeInfo tmp:subjectGradeInfoList) {
                if (Constants.ARCHIVED_STATUS_N.equals(tmp.getArchivedStatus())){
                    passFlag = Constants.ARCHIVED_STATUS_N;
                    break;
                }
            }
        }
        return passFlag;
    }

    /**
     * 查询考生成绩信息列表
     *
     * @param queryExamineeGradeVo 查询vo
     * @return 考生成绩信息
     */
    @Override
    public List<ExamindeGradeInfoRsp> selectGradeInfoPageList(QueryExamineeGradeVo queryExamineeGradeVo) {
        List<ExamindeGradeInfoRsp> rspList =  examineeGradeInfoMapper.selectGradeInfoPageList(queryExamineeGradeVo);
        if (CollectionUtils.isEmpty(rspList)){
            return new ArrayList<>();
        }
        List<String> grdeIds = rspList.stream().map(ExamindeGradeInfoRsp::getGradeId).collect(Collectors.toList());

        List<ExamineeSubjectGradeInfoVo> subjectGradeInfoVoList = subjectGradeInfoMapper.selectByGradeIds(grdeIds,queryExamineeGradeVo.getExamId(),queryExamineeGradeVo.getSubjectId());
        // 考生科目成绩map
        Map<String,List<ExamineeSubjectGradeInfoVo>> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(subjectGradeInfoVoList)){

            for (ExamineeSubjectGradeInfoVo vo: subjectGradeInfoVoList) {
                if (null !=map.get(vo.getGradeId())){
                    map.get(vo.getGradeId()).add(vo);
                }else {
                    List<ExamineeSubjectGradeInfoVo> list = new ArrayList<>();
                    list.add(vo);
                    map.put(vo.getGradeId(),list);
                }
            }
        }

        for (ExamindeGradeInfoRsp rsp: rspList) {
            if (null != map.get(rsp.getGradeId())){
                rsp.setSubjectGradeList(map.get(rsp.getGradeId()));
            }
        }
        return rspList;
    }

    @Override
    public List<ExamindeGradeInfoRsp> queryArchivedList(QueryExamineeGradeVo queryExamineeGradeVo) {
        List<ExamindeGradeInfoRsp> rspList =  examineeGradeInfoMapper.selectGradeInfoPageList(queryExamineeGradeVo);
        if (CollectionUtils.isEmpty(rspList)){
            return new ArrayList<>();
        }
        // 考试信息不为空则查出当前考试的的科目编号,否则查出当前考试名称对应的科目名称配置
        Map<String,String> subjectInfoMap = new HashMap<>();
        if (StringUtils.isNotEmpty(queryExamineeGradeVo.getExamId())){
            List<ExamSubjectVo> examSubjectVoList = subjectInfoMapper.selectExamSubjectInfoByExamId(queryExamineeGradeVo.getExamId());
            subjectInfoMap = examSubjectVoList.stream().collect(Collectors.toMap(ExamSubjectVo::getSubjectNameCode,ExamSubjectVo::getSubjectName));
        }else {
            ExamSubjectNameConfig examSubjectNameConfig = new ExamSubjectNameConfig();
            examSubjectNameConfig.setExamNameId(queryExamineeGradeVo.getExamNameConfigId());
            List<ExamSubjectNameConfig> configList = subjectNameConfigMapper.selectExamSubjectNameConfigList(examSubjectNameConfig);
            subjectInfoMap = configList.stream().collect(Collectors.toMap(ExamSubjectNameConfig::getSubjectNameCode,ExamSubjectNameConfig::getName));
        }
        for (ExamindeGradeInfoRsp rsp:rspList) {
            // 查询当前考生本年度以及以前考生所有的归档科目信息
            List<ExamineeSubjectGradeInfoVo> subjectGradeInfoVoList = subjectGradeInfoMapper.selectArchivedSubjectList(rsp.getExamineeIdCode(),queryExamineeGradeVo.getExamYear(),queryExamineeGradeVo.getSubjectId(),queryExamineeGradeVo.getExamNameConfigId());
            Map<String,ExamineeSubjectGradeInfoVo> subjectGradeInfoMap = subjectGradeInfoVoList.stream().collect(Collectors.toMap(ExamineeSubjectGradeInfoVo::getSubjectCode, Function.identity(),(key1, key2) -> key1));
            // 返回给展示的所有科目list
            List<ExamineeSubjectGradeInfoVo> showList = new ArrayList<>();

            // 遍历考试全部科目
            for (Map.Entry<String,String> entry:subjectInfoMap.entrySet()) {
                ExamineeSubjectGradeInfoVo tmp = new ExamineeSubjectGradeInfoVo();
                tmp.setSubjectCode(entry.getKey());
                tmp.setSubjectName(entry.getValue());
                if (null != subjectGradeInfoMap.get(tmp.getSubjectCode())){
                    showList.add(subjectGradeInfoMap.get(tmp.getSubjectCode()));
                }else {
                    showList.add(tmp);
                }

            }
            rsp.setSubjectGradeList(showList);
        }
        // 查询出当前考生的历史归档科目信息
        return rspList;
    }

    @Override
    public void insertGradeInfo(List<ImportGradeInfoVo> list) {
        log.info("插入成绩信息begin...总共插入{}条数据,每次插入200条成绩信息",list.size());
        //
        int insertNum =1;
        // 总共需要插入次数
        int totalInsertTimes = list.size()/ImportAbstractService.MAX_IMPORT+1;
        log.info("插入成绩信息,总共需要插入{}次",totalInsertTimes);
        // 需要插入的成绩信息和科目成绩信息
        List<ExamineeGradeInfo> insertGradeInfoList = new ArrayList<>();
        List<ExamineeSubjectGradeInfo> insertSubjectGradeInfoList = new ArrayList<>();
        // 当前插入次数
        int curInsertTime = 1;
        for (ImportGradeInfoVo gradeInfoVo:list) {
            insertGradeInfoList.add(gradeInfoVo.getExamineeGradeInfo());
            insertSubjectGradeInfoList.addAll(gradeInfoVo.getSubjectGradeInfoList());

            if (insertNum == ImportAbstractService.MAX_IMPORT){
                // 执行插入
                examineeGradeInfoMapper.batchInsertGradeInfo(insertGradeInfoList);
                subjectGradeInfoMapper.batchInsertSubjectGradeInfo(insertSubjectGradeInfoList);
                insertGradeInfoList.clear();
                insertSubjectGradeInfoList.clear();
                insertNum =0;
                curInsertTime ++;
            }else {
                // 最后一次插入数据如果小于200条也插入
                if(((curInsertTime-1)*ImportAbstractService.MAX_IMPORT+insertNum) == list.size()){
                    examineeGradeInfoMapper.batchInsertGradeInfo(insertGradeInfoList);
                    subjectGradeInfoMapper.batchInsertSubjectGradeInfo(insertSubjectGradeInfoList);
                }
            }
            insertNum ++;
        }

        log.info("插入成绩信息end...");
    }

    @Override
    public AjaxResult exportGradeInfo(BatchArchiveGradeVo queryExamineeGradeVo) {
        log.info("导出成绩信息begin..查询参数{}", JSON.toJSONString(queryExamineeGradeVo));
        List<ExamindeGradeInfoRsp> rspList =  selectExportGradeInfoList(queryExamineeGradeVo);
        String sheetName = getSheetName(queryExamineeGradeVo);
        List<ExamSubjectInfo> examSubjectInfoList = subjectInfoMapper.selectExamSubjectInfoListById(queryExamineeGradeVo.getExamId());
        if (CollectionUtils.isEmpty(examSubjectInfoList)){
            throw new CustomException("未找到考试对应的科目信息");
        }

        //Map<String,ExamSubjectInfo> map = examSubjectInfoList.stream().collect(Collectors.toMap(ExamSubjectInfo::getId,examSubjectInfo -> examSubjectInfo));
        return ExportUtils.doExport(rspList,sheetName,examSubjectInfoList);

    }

    private List<ExamindeGradeInfoRsp> selectExportGradeInfoList(BatchArchiveGradeVo queryExamineeGradeVo) {

        List<String> gradeIdList = new ArrayList<>();
        // 0-部分数据 1-当期全部数据
        if (Constants.ARCHIVE_TYPE_0.equals(queryExamineeGradeVo.getType()) && StringUtils.isNotEmpty(queryExamineeGradeVo.getGradeIds())){
            gradeIdList = Arrays.asList(queryExamineeGradeVo.getGradeIds().split(","));
            queryExamineeGradeVo.setGradeIdList(gradeIdList);
        }
        List<ExamindeGradeInfoRsp> rspList =  examineeGradeInfoMapper.selectExportGradeInfoList(queryExamineeGradeVo);
        if (CollectionUtils.isEmpty(rspList)){
            return new ArrayList<>();
        }
        //导出全部数据，无需传入考生信息
        List<String> grdeIds  ;
        if (Constants.ARCHIVE_TYPE_1.equals(queryExamineeGradeVo.getType())
            && StringUtils.isEmpty(queryExamineeGradeVo.getPassFlag())
            && StringUtils.isEmpty(queryExamineeGradeVo.getSearchValue())) {
            grdeIds = Lists.newArrayList();
        }else{
            grdeIds = rspList.stream().map(ExamindeGradeInfoRsp::getGradeId).collect(Collectors.toList());
        }

        List<ExamineeSubjectGradeInfoVo> subjectGradeInfoVoList = subjectGradeInfoMapper.selectByGradeIds(grdeIds,queryExamineeGradeVo.getExamId(),queryExamineeGradeVo.getSubjectId());
        // 考生科目成绩map
        Map<String,List<ExamineeSubjectGradeInfoVo>> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(subjectGradeInfoVoList)){

            for (ExamineeSubjectGradeInfoVo vo: subjectGradeInfoVoList) {
                if (null !=map.get(vo.getGradeId())){
                    map.get(vo.getGradeId()).add(vo);
                }else {
                    List<ExamineeSubjectGradeInfoVo> list = new ArrayList<>();
                    list.add(vo);
                    map.put(vo.getGradeId(),list);
                }
            }
        }

        for (ExamindeGradeInfoRsp rsp: rspList) {
            if (null != map.get(rsp.getGradeId())){
                rsp.setSubjectGradeList(map.get(rsp.getGradeId()));
            }
        }
        return rspList;
    }

    /**
     * 获取考试名称
     * @param queryExamineeGradeVo
     * @return
     */
    private String getSheetName(QueryExamineeGradeVo queryExamineeGradeVo){
        String sheetName = "";
        ExamNameConfig examNameConfig = nameConfigMapper.selectExamNameConfigById(queryExamineeGradeVo.getExamNameConfigId());
        sheetName = examNameConfig.getName();
        return sheetName;
    }

    @Override
    public AjaxResult downloadTemplate(QueryExamineeGradeVo queryExamineeGradeVo) {
        List<ExamSubjectVo> examSubjectInfoList = subjectInfoMapper.selectExamSubjectInfoByExamId(queryExamineeGradeVo.getExamId());
        if (CollectionUtils.isEmpty(examSubjectInfoList)){
            throw new CustomException("未找到考试对应的科目信息");
        }
        List<String>  subjcetCodeList = examSubjectInfoList.stream().map(ExamSubjectVo::getSubjectNameCode).collect(Collectors.toList());

        //return ExportUtils.downloadTemplate(ImportFieldConstants.getGradeFieldMap(),ImportFieldConstants.getSubjectGradeFieldMap(),examSubjectInfoList.size());
        return ExportUtils.downloadTemplate(ImportFieldConstants.getGradeFieldMap(),ImportFieldConstants.getSubjectGradeFieldMap(),subjcetCodeList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
   // @Async("threadPoolTaskExecutor")
    public void batchArchiveGrade(BatchArchiveGradeVo batchArchiveGradeVo, SysUser sysUser) {
        log.info("批量归档成绩begin...参数{},用户{}", JSON.toJSONString(batchArchiveGradeVo),sysUser.getUserName());
        Date curDate = DateUtils.getNowDate();
        // 0-部分数据归档 1-全部归档
        if (Constants.ARCHIVE_TYPE_1.equals(batchArchiveGradeVo.getType())){
            //  根据查询条件查找所有的考生信息
            List<ExamineeGradeInfo> rspList =  examineeGradeInfoMapper.selectUnarchivedGradeInfoList(batchArchiveGradeVo);
            if (CollectionUtils.isEmpty(rspList)){
                log.info("没有需要归档的考生信息");
                return;
            }
            syncBatchUpdateArchiveStatus(rspList,sysUser,batchArchiveGradeVo.getExamId());
        }else {
            //  根据考生成绩id更新考生归档状态
            if (StringUtils.isNotEmpty(batchArchiveGradeVo.getGradeIds())){
                List<String> gradeIds = Arrays.asList(batchArchiveGradeVo.getGradeIds().split(","));
                // 根据考生id查询未归档的考生信息
                List<ExamineeGradeInfo> gradeInfoList = examineeGradeInfoMapper.queryGradeInfoListByIds(gradeIds,batchArchiveGradeVo.getExamId(),Constants.ARCHIVED_STATUS_N);
                if (CollectionUtils.isEmpty(gradeInfoList)){
                    log.info("没有需要归档的考生信息");
                    return;
                }
                log.info("共需要归档{}个考生信息",gradeInfoList.size());
                for (ExamineeGradeInfo examineeGradeInfo:gradeInfoList) {
                    examineeGradeInfo.setUpdateBy(sysUser.getUserName());
                    examineeGradeInfo.setUpdateTime(curDate);
                    examineeGradeInfo.setArchivedStatus(Constants.ARCHIVED_STATUS_Y);
                    examineeGradeInfo.setArchivedDate(curDate);
                }
                batchUpdateArchiveStatus(gradeInfoList,batchArchiveGradeVo.getExamId(),curDate,sysUser.getUserName());

            }
        }
    }

    private final int BATCH_COUNT = 3000;
    /**
     * 异步批量插入成绩
     * @param list
     */
    public void syncBatchUpdateArchiveStatus(List<ExamineeGradeInfo> list, SysUser sysUser,String examId) {
        int count = list.size() % BATCH_COUNT == 0 ? list.size() / BATCH_COUNT : list.size() / BATCH_COUNT + 1;
        // 循环创建线程
        CountDownLatch countDownLatch = new CountDownLatch(count);
        List<FutureTask<Boolean>> resultList = Lists.newArrayList();
        for (int i = 0; i < count; i++) {
            List<ExamineeGradeInfo> gradeInfoVos = new ArrayList<>(BATCH_COUNT);
            if (i + 1 == count) {
                gradeInfoVos.addAll(list.subList(i * BATCH_COUNT, list.size()));
            } else {
                gradeInfoVos.addAll(list.subList(i * BATCH_COUNT, (i + 1) * BATCH_COUNT));
            }
            FutureTask<Boolean> future =  new FutureTask<>(new SyncBatchUpdateArchiveStatusTask(gradeInfoVos,countDownLatch,sysUser,examId));
            threadPoolTaskExecutor.submit(future);
            //将任务执行结果存储到List中
            resultList.add(future);
        }
        try {
            countDownLatch.await();
            for (FutureTask<Boolean> futureTask : resultList) {
                if(!futureTask.get()){
                    throw new CustomException(BizErrorCode.GRADE_E0010);
                }
            }
            log.info("异步更新归档完成" + DateUtils.localDateMillisToString(LocalDateTime.now()));
        } catch (InterruptedException e) {
            log.error(e.getCause().getMessage());
            Thread.currentThread().interrupt();
            throw new CustomException(BizErrorCode.GRADE_E0010);
        } catch (ExecutionException e) {
            //看看失败原因
            log.error(e.getCause().getMessage());
            throw new CustomException(BizErrorCode.GRADE_E0010);
        }
    }

    /**
     * 异步更新成绩处理
     */
    public class SyncBatchUpdateArchiveStatusTask  implements Callable<Boolean> {
        private List<ExamineeGradeInfo> gradeInfoVos;
        private SysUser sysUser;
        private String examId;
        private CountDownLatch countDownLatch;

        public SyncBatchUpdateArchiveStatusTask(List<ExamineeGradeInfo> gradeInfoVos,
            CountDownLatch countDownLatch,SysUser sysUser,String examId) {
            this.gradeInfoVos = gradeInfoVos;
            this.countDownLatch = countDownLatch;
            this.sysUser = sysUser;
            this.examId = examId;
        }

        @Override
        public Boolean call(){
            try {
                log.info("SaveData size: {}", gradeInfoVos.size());
                IExamineeGradeInfoService gradeInfoService = SpringUtils.getBean(IExamineeGradeInfoService.class);
                gradeInfoService.batchCountUpdateArchiveStatus(gradeInfoVos,sysUser,DateUtils.getNowDate(),examId);
                return true;
            } finally {
                countDownLatch.countDown();
            }
        }
    }

    @Override
    public void batchCountUpdateArchiveStatus(List<ExamineeGradeInfo> rspList, SysUser sysUser,
        Date curDate, String examId){
        List<ExamineeGradeInfo> eaInfoList = new ArrayList<>();
        // 分页处理数据,每次处理500条
        for (ExamineeGradeInfo examineeGradeInfo:rspList) {
            examineeGradeInfo.setUpdateBy(sysUser.getUserName());
            examineeGradeInfo.setUpdateTime(curDate);
            examineeGradeInfo.setArchivedStatus(Constants.ARCHIVED_STATUS_Y);
            examineeGradeInfo.setArchivedDate(curDate);
            eaInfoList.add(examineeGradeInfo);
        }
        // 分批每次插入300条考生数据
        log.info("分批归档考生成绩信息,总共有{}个考生信息",eaInfoList.size());
        int total = rspList.size();
        int i=0;
        while (total > Constants.ARCHIVE_SIZE) {
            List<ExamineeGradeInfo> updateList  = rspList.subList(i,i+Constants.ARCHIVE_SIZE);
            batchUpdateArchiveStatus(updateList,examId,curDate,sysUser.getUserName());
            i = i + Constants.ARCHIVE_SIZE;
            total = total - Constants.ARCHIVE_SIZE;
        }
        if (total > 0) {
            List<ExamineeGradeInfo> updateList  = rspList.subList(i,i+total);
            batchUpdateArchiveStatus(updateList,examId,curDate,sysUser.getUserName());
        }
    }

    /**
     * 批量归档考生成绩和考生科目成绩
     * @param updateList
     * @param examId
     * @param curDate
     * @param userName
     */
    private void batchUpdateArchiveStatus(List<ExamineeGradeInfo> updateList,String examId,Date curDate,String userName){
        List<String> gradeIds = updateList.stream().map(ExamineeGradeInfo::getGradeId).collect(Collectors.toList());
        // 批量归档考生信息
        examineeGradeInfoMapper.batchUpdateExamineeGradeInfo(updateList);
        // 批量归档考生成绩信息
        List<ExamineeSubjectGradeInfo> examineeSubjectGradeInfoList = subjectGradeInfoMapper.querySubjectGradeInfoListByIds(gradeIds);
        if (CollectionUtils.isEmpty(examineeSubjectGradeInfoList)){
            log.info("没有需要归档的考生科目信息");
            return;
        }
        setValidGradeDate(examineeSubjectGradeInfoList,examId,curDate,userName);
        //  更新所有科目成绩为归档
        subjectGradeInfoMapper.batchUpdateSbujectGradeInfo(examineeSubjectGradeInfoList);
    }

    /**
     * 设置归档后科目成绩有效期
     * @param examineeSubjectGradeInfoList
     * @param examId
     * @param curDate
     */
    private void setValidGradeDate(List<ExamineeSubjectGradeInfo> examineeSubjectGradeInfoList,String  examId,Date curDate,String userName){
        // 设置成绩有效期,查询出该考生对应的所有考试科目以及有效期
        List<ExamSubjectInfo> examSubjectInfoList = subjectInfoMapper.querySubjectEffectiveDateByExamId(examId);
        // 考试科目有效日期map
        Map<String,String> effectiveDateMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(examSubjectInfoList)){
            effectiveDateMap = examSubjectInfoList.stream().collect(Collectors.toMap(ExamSubjectInfo::getId,ExamSubjectInfo::getEffectiveDate));
        }
        // 考生成绩对应的科目成绩列表
        for (ExamineeSubjectGradeInfo examineeSubjectGradeInfo: examineeSubjectGradeInfoList) {
            // 已归档的不需要再重新归档
            if (null != effectiveDateMap.get(examineeSubjectGradeInfo.getSubjectId())){
                examineeSubjectGradeInfo.setArchivedDate(curDate);
                examineeSubjectGradeInfo.setArchivedStatus(Constants.ARCHIVED_STATUS_Y);
                examineeSubjectGradeInfo.setValidPeriodStartDate(DateUtils.getDate());
                String endData = getValidPeriodEndDate(effectiveDateMap.get(examineeSubjectGradeInfo.getSubjectId()));
                examineeSubjectGradeInfo.setValidPeriodEndDate(endData);
                examineeSubjectGradeInfo.setInvalidDate(endData);
                examineeSubjectGradeInfo.setUpdateBy(userName);
                examineeSubjectGradeInfo.setUpdateTime(curDate);
            }
        }
    }

    @Override
    public boolean seleExamineeCountById(String examId) {
        int total = examineeGradeInfoMapper.seleExamineeCountById(examId);
        if (total > 0){
            return true;
        }
        return false;
    }
}
